﻿using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Reflection;
using System.Xml.Serialization;
using System.Collections.Generic;

namespace Ayatta.Common.Extension
{
    public static class TypeExtension
    {
        public static object[] BuildTypeConstructorParametersFromContainer(this Type type, Func<ParameterInfo, object> getParameterObject)
        {
            var constructor = type.GetLargestConstructor();
            var constructorParameters = constructor.GetParameters();
            var parameters = new List<object>(constructorParameters.Length);
            parameters.AddRange(constructorParameters.Select(getParameterObject));

            return parameters.ToArray();
        }

        public static ConstructorInfo GetLargestConstructor(this Type type)
        {
            return type.GetLargestConstructor(BindingFlags.Public | BindingFlags.Instance);
        }

        public static ConstructorInfo GetLargestConstructor(this Type type, BindingFlags bindings)
        {
            ConstructorInfo foundConstructor = null;
            var constructors = type.GetConstructors(bindings);
            foreach (var constructor in constructors)
            {
                if (foundConstructor == null ||constructor.GetParameters().Length > foundConstructor.GetParameters().Length)
                    foundConstructor = constructor;
            }
            return foundConstructor;
        }

        public static XElement SerializeValue(this Type type, object value)
        {
            var serializer = new XmlSerializer(type);
            var stream = new MemoryStream();
            var writer = new XmlTextWriter(stream, Encoding.UTF8);

            serializer.Serialize(writer, value);

            var xml =Encoding.UTF8.GetString(((MemoryStream)writer.BaseStream).ToArray());

            xml = xml.Replace("<?xml version=\"1.0\" encoding=\"utf-8\"?>", "");
            xml = string.Format("<Value>{0}</Value>", xml);

            return XElement.Parse(xml);
        }

        public static object DeserializeValue(this Type type, XElement value)
        {
            var serializer = new XmlSerializer(type);
            var stream = new MemoryStream(new UTF8Encoding().GetBytes("<?xml version=\"1.0\" encoding=\"utf-8\"?>" + value.Descendants().ElementAt(0)));
            return serializer.Deserialize(stream);
        }
    }
}
